﻿using BattleFury.Lib.Graphics;
using BattleFury.Lib.Input;
using BattleFury.Lib.Logs;
using BattleFury.Lib.Network;
using BattleFury.Lib.Screens;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using TextureCollection = BattleFury.Lib.Collections.TextureCollection;

namespace BattleFury.Lib
{
    public class RenderEngine : Game
    {
        #region Variables / Properties

        private Vector2 _resolution;
        private readonly GraphicsDeviceManager _graphics;

        public SpriteBatch SpriteBatch { get; set; }

        public TextureCollection Textures { get; set; }
        public ScreenCollection Screens { get; set; }

        public InputManager Input { get; set; }
        public LogManager Logs { get; set; }

        public bool NetworkEnabled { get; set; }
        public string AppIdentifier { get; set; }
        public string Host { get; set; }
        public int Port { get; set; }
        public NetworkClient NetworkClient { get; set; }

        public Vector2 Resolution
        {
            get { return _resolution; }
            set { ChangeResolution(value); }
        }

        public GraphicsDeviceManager Graphics
        {
            get { return _graphics; }
        }

        #endregion

        #region Events
        public delegate void AfterInitializeScreensEventHandler(object source, object e);
        public event AfterInitializeScreensEventHandler AfterInitializeScreens;

        public delegate void LoadAdditionalContentEventHandler(object source, object e);
        public event LoadAdditionalContentEventHandler LoadAdditionalContent;

        //public delegate void AfterInitializeNetworkEventHandler(object source, object e);
        //public event AfterInitializeNetworkEventHandler AfterInitializeNetwork;


        #endregion

        #region Initialization
        private static RenderEngine _engine = null;
        public static RenderEngine Get()
        {
            if (_engine == null)
                _engine = new RenderEngine();
            return _engine;
        }

        private RenderEngine()
        {
            _graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            NetworkEnabled = false;
            AppIdentifier = "Fury";
            Host = "localhost";
            Port = 28657;
        }

        protected override void Initialize()
        {
            InitializeCollections();
            LoadAdditionalContent(this, null);

            InitializeManagers();

            InitializeScreens();
            AfterInitializeScreens(this, null);

            InitializeNetwork();
            //AfterInitializeNetwork(this, null);

            base.Initialize();
        }

        protected virtual void InitializeManagers()
        {
            Logs = new LogManager();
            Input = new InputManager();

#if !DEBUG
				Logs.IsEnabled = false;
#endif
        }

        protected virtual void InitializeCollections()
        {
            Textures = new TextureCollection();
            Screens = new ScreenCollection();
        }

        protected virtual void InitializeScreens()
        {

        }

        protected virtual void InitializeNetwork()
        {
            if (!NetworkEnabled) return;
            NetworkClient = new NetworkClient(AppIdentifier, Host, Port);
        }

        protected override void LoadContent()
        {
            SpriteBatch = new SpriteBatch(GraphicsDevice);

            Textures.Add("WhitePixel", GraphicsHelper.WhitePixel(_graphics.GraphicsDevice));

            LoadInitialContent();
        }

        protected virtual void LoadInitialContent()
        {
            //// ReSharper disable ForCanBeConvertedToForeach
            for (var i = 0; i < Screens.Count; i++)
            {
                var screen = Screens[i];
                screen.LoadContent();
            }
            //// ReSharper restore ForCanBeConvertedToForeach
        }

        #endregion

        #region Update

        protected override void Update(GameTime gameTime)
        {
            UpdateManagers(gameTime);

            Screens.Update(gameTime);
        }

        protected virtual void UpdateManagers(GameTime gameTime)
        {
            Logs.Update(gameTime);
            Input.Update(gameTime);
        }

        #endregion

        #region Draw

        protected override void Draw(GameTime gameTime)
        {
            Screens.Draw(gameTime);
        }

        #endregion

        #region Utility Methods

        public void ChangeResolution(int width, int height)
        {
            _resolution = new Vector2(width, height);
            _graphics.PreferredBackBufferWidth = width;
            _graphics.PreferredBackBufferHeight = height;
            _graphics.ApplyChanges();
        }

        public void ChangeResolution(Vector2 resolution)
        {
            ChangeResolution((int)resolution.X, (int)resolution.Y);
        }

        #endregion

        #region Log Methods

        public void Log(string message)
        {
            Logs.Log(message);
        }

        public void LogMessage(string message)
        {
            Logs.Log(message);
        }

        public void LogInfo(string message)
        {
            Logs.Log(LogMessageType.Info, message);
        }

        public void LogWarning(string message)
        {
            Logs.Log(LogMessageType.Warning, message);
        }

        public void LogError(string message)
        {
            Logs.Log(LogMessageType.Error, message);
        }

        #endregion

       
    }
}